package cn.com.ebidding.file;

import cn.com.ebidding.file.entity.VirtualFile;
import cn.com.ebidding.file.util.FileUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @program: blog
 * @description:
 * @author: wfy
 * @create: 2019-03-01 09:51
 */
@Component
public class FtpApiClient extends BaseApiClient{
    public static final String SEPARATOR = "/";
    @Value("${ftp.port}")
    private int port;
    @Value("${ftp.host}")
    private String host;
    @Value("${ftp.baseDir}")
    private String baseDir;
    @Value("${ftp.username}")
    private String username;
    @Value("${ftp.password}")
    private String password;

    public FtpApiClient() {
        super("ftp");
    }

    @Override
    protected void check() {
        //TODO 待分环境配置后再补充
    }

    @Override
    public VirtualFile upload(InputStream is, String key) {
        FTPClient ftpClient = null;
        Date startTime = new Date();
        try {
            ftpClient = getFtpClient();
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            String dir = generateDirs();
            boolean changeDirOk = ftpClient.changeWorkingDirectory(dir);
            this.createNewFileName(key, "");
            if (!changeDirOk) {
                makeDirs(ftpClient, dir);
            }
            // Use passive mode to pass firewalls.
//            ftpClient.enterLocalPassiveMode();
            boolean uploadOk = ftpClient.storeFile(newFileName, is);
            if (!uploadOk)
                throw new Exception("上传 " + dir + SEPARATOR + newFileName + " 失败!");
            return new VirtualFile()
                    .setOriginalFileName(FileUtil.getName(key))
                    .setSuffix(this.suffix)
                    .setUploadStartTime(startTime)
                    .setUploadEndTime(new Date())
                    .setFilePath(this.newFileName)
//                    .setFileHash(DigestUtils.md5DigestAsHex(fileHashIs))
                    .setFullFilePath(dir);
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            IOUtils.closeQuietly(is);
            disconnect(ftpClient);
        }
    }

    @Override
    public boolean removeFile(String key) {
        return false;
    }

    public void download(OutputStream out, String fullFilePath, String newFileName) {
        FTPClient ftpClient = null;
        try {
            ftpClient = getFtpClient();
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            // Use passive mode to pass firewalls.
//            ftpClient.enterLocalPassiveMode();
            ftpClient.changeWorkingDirectory(fullFilePath);
            boolean downloadOk = ftpClient.retrieveFile(newFileName, out);
            if (!downloadOk)
                throw new RuntimeException("下载 " + newFileName + " 失败!");
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            disconnect(ftpClient);
        }
    }


    private FTPClient getFtpClient() throws Exception {

        try {
            FTPClient ftpClient = new FTPClient();
            ftpClient.setDefaultTimeout(10 * 1000);
            ftpClient.setConnectTimeout(10 * 1000);
            ftpClient.setDataTimeout(30 * 1000);
            ftpClient.setDefaultPort(port);
            ftpClient.connect(host);

            int reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                disconnect(ftpClient);
                throw new IOException("无法连接ftp服务器");
            }

            // Login.
            if (!ftpClient.login(username, password)) {
                disconnect(ftpClient);
                throw new IOException("登录ftp服务器失败，用户名或密码错误！");
            }

            return ftpClient;
        } catch (Exception e) {
            throw e;
        }
    }

    public void disconnect(FTPClient ftpClient) {
        try {
            if (ftpClient != null && ftpClient.isConnected()) {
                ftpClient.logout();
                ftpClient.disconnect();
            }
        } catch (Exception e) {
        }
    }

    public void makeDirs(FTPClient ftpClient, String dirName) throws Exception {

        File dir = new File(dirName);
        String currentDirName = dir.getName();
        if (dir.getParent() != null) {
            makeDirs(ftpClient, dir.getParent());
        }
        makeDir(ftpClient, currentDirName);
    }

    public void makeDir(FTPClient ftpClient, String dirName) throws Exception {

        try {
            boolean changeDirOk = ftpClient.changeWorkingDirectory(dirName);
            if (!changeDirOk) {
                boolean a =ftpClient.makeDirectory(dirName);
                changeDirOk = ftpClient.changeWorkingDirectory(dirName);
            }
            if (!changeDirOk)
                throw new Exception("创建ftp目录" + dirName + "失败！");
        } catch (Exception e) {
            throw e;
        }
    }

    private String generateDirs() {
        String dateDir = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
        return baseDir + SEPARATOR + dateDir;
    }

    public static void main(String[] args) throws FileNotFoundException {
        FtpApiClient ftpApiClient = new FtpApiClient();
        ftpApiClient.port=21;
        ftpApiClient.baseDir="ebs-ksp";
        ftpApiClient.password="ebs@ftp";
        ftpApiClient.host="47.111.67.64";
        ftpApiClient.username="ftp";
        FileInputStream f = new FileInputStream(new File("/Users/wfy/Downloads/测试.PNG"));
        System.out.println(ftpApiClient.upload(f,"测试.PNG"));
    }


}
